package pl.us.ij.plugins.segmentation.forms;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import pl.us.ij.plugins.segmentation.SegmentationPlugIn;
import pl.us.ij.plugins.segmentation.SwitchImageListener;
import pl.us.ij.plugins.segmentation.Trace;
import pl.us.ij.plugins.segmentation.infrastructure.CategoryInfo;
import pl.us.ij.plugins.segmentation.infrastructure.CommandParams;
import pl.us.ij.plugins.segmentation.infrastructure.ICommandInvokeHandler;
import pl.us.ij.plugins.segmentation.infrastructure.ShowPixelValuesCommand;

import javax.swing.*;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ResourceBundle;

public class ControlTemplateForm implements IActionHandler {
    private JPanel panelForm;
    private JTree navigationTree;
    private JPanel titlePanel;
    private JButton undoButton;
    private JPanel contentPanel;
    private JLabel titleLabel;
    private JPanel topPanel;
    private JPanel bottomPanel;
    private JLabel descriptionLabel;
    private ChannelForm channelForm;
    private JCheckBox logCheckBox;
    private ICommandInvokeHandler commandInvokeHandler;


    public ControlTemplateForm(ICommandInvokeHandler cmdInvokeHandler) {

        this.commandInvokeHandler = cmdInvokeHandler;

        this.channelForm.setBlue(true);
        this.channelForm.setRed(true);
        this.channelForm.setGreen(true);

        this.logCheckBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Trace.setLogging(logCheckBox.isSelected());
            }
        });
        this.logCheckBox.setSelected(Trace.getLogging());

        setupNavigationTree();
        setAction(undoButton, ShowPixelValuesCommand.class, null);
    }

    private void setupNavigationTree() {

        ImageIcon leafIcon = createImageIcon("plugins\\Segmentation\\Right24.gif");
        ImageIcon rootIcon = createImageIcon("plugins\\Segmentation\\Down24.gif");

        if (leafIcon != null && rootIcon != null) {
            DefaultTreeCellRenderer renderer =
                    new DefaultTreeCellRenderer();
            renderer.setLeafIcon(leafIcon);
            renderer.setOpenIcon(rootIcon);
            this.navigationTree.setCellRenderer(renderer);
        }


        this.navigationTree.setModel(getNavigationTreeModel());

        this.navigationTree.addTreeWillExpandListener(new TreeWillExpandListener() {
            @Override
            public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {

            }

            @Override
            public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
                throw new ExpandVetoException(event);
            }
        });

        this.navigationTree.addTreeSelectionListener(new TreeSelectionListener() {
            @Override
            public void valueChanged(TreeSelectionEvent e) {

                JPanel contentPanel = topPanel;

                DefaultMutableTreeNode node = (DefaultMutableTreeNode)
                        ((JTree) e.getSource()).getLastSelectedPathComponent();

                if (node.getUserObject() instanceof CategoryInfo) {
                    CategoryInfo catInfo = (CategoryInfo) node.getUserObject();

                    if (!(contentPanel.getLayout() instanceof BorderLayout))
                        contentPanel.setLayout(new BorderLayout());

                    contentPanel.removeAll();

                    if (catInfo.getPanel() != null)
                        contentPanel.add(catInfo.getPanel());

                    if (catInfo instanceof SwitchImageListener) {
                        SegmentationPlugIn.addSwitchImageListener((SwitchImageListener) catInfo, true);
                    }

                    contentPanel.updateUI();

                    descriptionLabel.setText(catInfo.getDescription());
                    descriptionLabel.updateUI();

                    String prefix = "";

                    if (node.getParent() instanceof DefaultMutableTreeNode)
                        if (((DefaultMutableTreeNode) node.getParent()).getUserObject() instanceof CategoryInfo)
                            prefix = ((CategoryInfo) ((DefaultMutableTreeNode) node.getParent()).getUserObject()).getTitle() +
                                    ": ";

                    titleLabel.setText(prefix + catInfo.getTitle());
                    titleLabel.updateUI();
                }

            }
        });

        this.navigationTree.setRootVisible(false);
        for (int row = 0; row < this.navigationTree.getRowCount(); row++)
            this.navigationTree.expandRow(row);

        navigationTree.setSelectionRow(navigationTree.getRowCount() - 1);
    }

    private ImageIcon createImageIcon(String filename) {
        return new ImageIcon(filename);
    }

    private TreeModel getNavigationTreeModel() {
        DefaultMutableTreeNode top =
                new DefaultMutableTreeNode("Navigation");

        DefaultMutableTreeNode category = null;

        TreeModel treeModel = new DefaultTreeModel(top);

        top.add(category = new DefaultMutableTreeNode(new FiltersIntroForm()));

        category.add(new DefaultMutableTreeNode(new FilterGaussForm(this)));
        category.add(new DefaultMutableTreeNode(new FilterMedianForm(this)));
        category.add(new DefaultMutableTreeNode(new FilterAveragedForm(this)));

        top.add(category = new DefaultMutableTreeNode(new ThresholdsIntroForm()));
        category.add(new DefaultMutableTreeNode(new ThresholdsAutoForm(this)));
        category.add(new DefaultMutableTreeNode(new ThresholdsOneLevelForm(this)));
        category.add(new DefaultMutableTreeNode(new ThresholdsTwoLevelForm(this)));

        top.add(category = new DefaultMutableTreeNode(new EdgesIntroForm()));
        category.add(new DefaultMutableTreeNode(new EdgesMasksForm(this)));
        category.add(new DefaultMutableTreeNode(new EdgesDilationErosionForm(this)));
        category.add(new DefaultMutableTreeNode(new EdgesSkeletonizationForm(this)));

        top.add(category = new DefaultMutableTreeNode(new WatershedForm(this)));
        top.add(category = new DefaultMutableTreeNode(new OpenCloseForm(this)));
        top.add(category = new DefaultMutableTreeNode(new CVTForm(this)));

        top.add(category = new DefaultMutableTreeNode(new PrairieFireForm(this)));
        top.add(category = new DefaultMutableTreeNode(new AboutForm(this)));


        return treeModel;
    }

    public static JFrame getFrame() {
        JFrame frame = new JFrame("");
        frame.setContentPane(new ControlTemplateForm(new DummyCommandInvokeHandler()).panelForm);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(825, 600);
//        frame.pack();
        frame.setVisible(true);

        return frame;
    }

    public static JPanel getMainPanel(ICommandInvokeHandler cmdInvokeHandler) {
        return new ControlTemplateForm(cmdInvokeHandler).panelForm;
    }

    public static void main(String[] args) {
        JFrame frame = getFrame();
    }

    @Override
    public <T> void setAction(JButton button, Class<T> commandClass, final ICommandParamGather commandParamGather) {
        button.setAction(getCommandAction(button.getText(), commandClass.getSimpleName(), new ICommandParamGather() {
            @Override
            public CommandParams getCommandParams() {
                CommandParams params;

                if (commandParamGather == null)
                    params = new CommandParams();
                else
                    params = commandParamGather.getCommandParams();

                params.setUseBlue(channelForm.isBlue());
                params.setUseRed(channelForm.isRed());
                params.setUseGreen(channelForm.isGreen());

                return params;
            }
        }));
    }

    private CommandAction getCommandAction(String text, String commandName, ICommandParamGather paramGather) {
        if (paramGather == null) {
            paramGather = new ICommandParamGather() {
                public CommandParams getCommandParams() {
                    return new CommandParams();
                }
            };
        }

        return new CommandAction(text, commandName, this.commandInvokeHandler, paramGather);
    }

    {
// GUI initializer generated by IntelliJ IDEA GUI Designer
// >>> IMPORTANT!! <<<
// DO NOT EDIT OR ADD ANY CODE HERE!
        $$$setupUI$$$();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        panelForm = new JPanel();
        panelForm.setLayout(new FormLayout("fill:d:grow", "center:d:grow"));
        final JSplitPane splitPane1 = new JSplitPane();
        CellConstraints cc = new CellConstraints();
        panelForm.add(splitPane1, cc.xy(1, 1, CellConstraints.DEFAULT, CellConstraints.FILL));
        navigationTree = new JTree();
        navigationTree.setRootVisible(true);
        navigationTree.setShowsRootHandles(true);
        splitPane1.setLeftComponent(navigationTree);
        final JPanel panel1 = new JPanel();
        panel1.setLayout(new FormLayout("fill:d:grow,left:d:noGrow,fill:max(d;4px):noGrow", "center:d:grow"));
        splitPane1.setRightComponent(panel1);
        final JPanel panel2 = new JPanel();
        panel2.setLayout(new FormLayout("fill:d:grow", "center:38px:noGrow,top:d:noGrow,fill:max(d;4px):grow"));
        panel1.add(panel2, cc.xy(1, 1, CellConstraints.DEFAULT, CellConstraints.FILL));
        titlePanel = new JPanel();
        titlePanel.setLayout(new FormLayout("fill:d:grow", "fill:d:grow"));
        titlePanel.setBackground(SystemColor.window);
        panel2.add(titlePanel, cc.xy(1, 1));
        titlePanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), null));
        titleLabel = new JLabel();
        titleLabel.setFont(new Font(titleLabel.getFont().getName(), Font.BOLD, 20));
        titleLabel.setHorizontalAlignment(0);
        titleLabel.setHorizontalTextPosition(0);
        titleLabel.setText("");
        titlePanel.add(titleLabel, cc.xy(1, 1));
        contentPanel = new JPanel();
        contentPanel.setLayout(new FormLayout("fill:d:grow", "fill:d:noGrow,top:4dlu:noGrow,center:max(d;4px):grow"));
        panel2.add(contentPanel, cc.xy(1, 3, CellConstraints.DEFAULT, CellConstraints.FILL));
        contentPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), null));
        topPanel = new JPanel();
        topPanel.setLayout(new FormLayout("fill:d:noGrow", "center:d:grow"));
        contentPanel.add(topPanel, cc.xy(1, 1, CellConstraints.DEFAULT, CellConstraints.FILL));
        final com.intellij.uiDesigner.core.Spacer spacer1 = new com.intellij.uiDesigner.core.Spacer();
        topPanel.add(spacer1, cc.xy(1, 1, CellConstraints.DEFAULT, CellConstraints.FILL));
        bottomPanel = new JPanel();
        bottomPanel.setLayout(new FormLayout("fill:d:grow", "fill:100px:grow"));
        contentPanel.add(bottomPanel, cc.xy(1, 3, CellConstraints.DEFAULT, CellConstraints.FILL));
        descriptionLabel = new JLabel();
        descriptionLabel.setBackground(new Color(-1));
        descriptionLabel.setHorizontalTextPosition(10);
        descriptionLabel.setText("");
        descriptionLabel.setVerticalAlignment(1);
        descriptionLabel.putClientProperty("html.disable", Boolean.FALSE);
        bottomPanel.add(descriptionLabel, cc.xy(1, 1, CellConstraints.DEFAULT, CellConstraints.FILL));
        final JPanel panel3 = new JPanel();
        panel3.setLayout(new FormLayout("fill:d:grow,left:d:noGrow,fill:d:noGrow", "center:d:noGrow,top:d:noGrow,fill:max(d;4px):grow"));
        panel1.add(panel3, cc.xy(3, 1, CellConstraints.DEFAULT, CellConstraints.FILL));
        channelForm = new ChannelForm();
        panel3.add(channelForm.$$$getRootComponent$$$(), cc.xy(3, 1, CellConstraints.DEFAULT, CellConstraints.TOP));
        final JPanel panel4 = new JPanel();
        panel4.setLayout(new FormLayout("fill:d:grow", "bottom:d:noGrow,top:4dlu:noGrow,center:max(d;4px):noGrow,top:4dlu:noGrow,fill:104px:grow"));
        panel3.add(panel4, cc.xy(3, 3, CellConstraints.DEFAULT, CellConstraints.FILL));
        panel4.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), null));
        undoButton = new JButton();
        this.$$$loadButtonText$$$(undoButton, ResourceBundle.getBundle("pl/us/ij/plugins/segmentation/localization/Localization").getString("controlTemplateForm.showPixelValues"));
        panel4.add(undoButton, cc.xy(1, 5, CellConstraints.DEFAULT, CellConstraints.BOTTOM));
        logCheckBox = new JCheckBox();
        this.$$$loadButtonText$$$(logCheckBox, ResourceBundle.getBundle("pl/us/ij/plugins/segmentation/localization/Localization").getString("controlTemplateForm.logExceptionsLabel"));
        panel4.add(logCheckBox, cc.xy(1, 3, CellConstraints.DEFAULT, CellConstraints.BOTTOM));
    }

    /**
     * @noinspection ALL
     */
    private void $$$loadButtonText$$$(AbstractButton component, String text) {
        StringBuffer result = new StringBuffer();
        boolean haveMnemonic = false;
        char mnemonic = '\0';
        int mnemonicIndex = -1;
        for (int i = 0; i < text.length(); i++) {
            if (text.charAt(i) == '&') {
                i++;
                if (i == text.length()) break;
                if (!haveMnemonic && text.charAt(i) != '&') {
                    haveMnemonic = true;
                    mnemonic = text.charAt(i);
                    mnemonicIndex = result.length();
                }
            }
            result.append(text.charAt(i));
        }
        component.setText(result.toString());
        if (haveMnemonic) {
            component.setMnemonic(mnemonic);
            component.setDisplayedMnemonicIndex(mnemonicIndex);
        }
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return panelForm;
    }

    private static class DummyCommandInvokeHandler implements ICommandInvokeHandler {
        public void invoke(String commandName) {
            JOptionPane.showMessageDialog(null, commandName);
        }

        public void invoke(String commandName, CommandParams params) {
            invoke(commandName);
        }
    }
}
